package com.deer.wms.instock.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.deer.wms.ASN.manage.constant.AsnManageConstant;
import com.deer.wms.ASN.manage.dao.AsnDetailMapper;
import com.deer.wms.ASN.manage.dao.AsnMasterMapper;
import com.deer.wms.ASN.manage.model.AsnCodeDetail;
import com.deer.wms.ASN.manage.model.asn.AsnDetail;
import com.deer.wms.ASN.manage.model.asn.AsnMaster;
import com.deer.wms.ASN.manage.model.in.AcceptRecord;
import com.deer.wms.ASN.manage.service.AcceptRecordService;
import com.deer.wms.ASN.manage.service.AsnCodeDetailService;
import com.deer.wms.ASN.manage.service.AsnDetailService;
import com.deer.wms.ASN.manage.service.AsnMasterService;
import com.deer.wms.base.system.dao.ErpBackRecordMapper;
import com.deer.wms.base.system.dao.SuppInfoMapper;
import com.deer.wms.base.system.model.*;
import com.deer.wms.base.system.model.Area.AreaInfo;
import com.deer.wms.base.system.model.Cell.CellInfo;
import com.deer.wms.base.system.model.Item.ItemInfo;
import com.deer.wms.base.system.model.Supplier.SupplierInfo;
import com.deer.wms.base.system.service.AreaInfoService;
import com.deer.wms.base.system.service.CellInfoService;
import com.deer.wms.base.system.service.ItemInfoService;
import com.deer.wms.instock.constant.InStockConstant;
import com.deer.wms.instock.dao.TransferBillMapper;
import com.deer.wms.instock.model.Allot.TransferBillCriteria;
import com.deer.wms.instock.model.disptch.DispatCriteria;
import com.deer.wms.instock.model.transfer.PackBox;
import com.deer.wms.instock.model.transfer.PackBoxData;
import com.deer.wms.instock.model.transfer.TransferBill;
import com.deer.wms.instock.model.transfer.UpperData;
import com.deer.wms.instock.service.TransferBillService;
import com.deer.wms.instock.service.enter.StrategyEnterService;
import com.deer.wms.intercept.common.data.CurrentUser;
import com.deer.wms.inventory.constant.InventoryConstant;
import com.deer.wms.inventory.model.Inventory.*;
import com.deer.wms.inventory.service.InventoryService;
import com.deer.wms.inventory.service.InventoryTransactService;
import com.deer.wms.inventory.service.ItemBatchService;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.service.SuperServiceImpl;
import com.deer.wms.project.root.util.DateUtils;
import com.deer.wms.project.root.util.StringUtils;
import com.deer.wms.system.manage.constant.SystemManageConstant;
import com.deer.wms.system.manage.model.DataDictDetail;
import com.deer.wms.system.manage.model.dept.Dept;
import com.deer.wms.system.manage.model.ware.WareInfo;
import com.deer.wms.system.manage.service.*;
import com.deer.wms.ware.task.config.StrategyErpService;
import com.deer.wms.ware.task.constant.WareTaskConstant;
import com.deer.wms.ware.task.erp.UpdatePPF;
import com.deer.wms.ware.task.model.ErpPushLog;
import com.deer.wms.ware.task.model.ErpPushLogInfo;
import com.deer.wms.ware.task.model.SO.SoDetail;
import com.deer.wms.ware.task.model.SO.SoMaster;
import com.deer.wms.ware.task.model.SO.contrast.ContrastVo;
import com.deer.wms.ware.task.model.SO.vo.SoDetailVo;
import com.deer.wms.ware.task.model.Wave.WaveDetail;
import com.deer.wms.ware.task.model.out.OutDetail;
import com.deer.wms.ware.task.model.pushErp.beasAssist.BaseAssist;
import com.deer.wms.ware.task.service.*;
import com.deer.wms.ware.task.service.impl.SoMasterServiceImpl;
import com.google.common.base.Preconditions;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.deer.wms.project.root.util.CollectionUtils.convertMap;
import static com.deer.wms.project.root.util.CollectionUtils.distinct;

/**
 * @author : wei
 * @since : 2022-01-08 20:43:41
 **/
@Service
@Transactional
@Slf4j
public class TransferBillServiceImpl extends SuperServiceImpl<TransferBillMapper, TransferBill> implements TransferBillService {

    @Value("${wave.direct}")
    //直发虚仓
    private Integer directId;
    @Value("${wave.vmi}")
    //VMI仓库id
    private Integer vmiId;
    @Autowired
    private ValidatorService validatorService;
    @Autowired
    private DataDictDetailService dataDictDetailService;


    @Autowired
    private CodeRuleService codeRuleService;
    @Autowired
    private InventoryTransactService inventoryTransactService;
    @Autowired
    private WareInfoService wareInfoService;
    @Autowired
    private CellInfoService cellInfoService;
    @Autowired
    private ItemInfoService itemInfoService;
    @Autowired
    private ItemBatchService itemBatchService;
    @Autowired
    private TransferBillMapper transferBillMapper;
    @Autowired
    private AsnMasterMapper asnMasterMapper;
    @Autowired
    private AsnDetailMapper asnDetailMapper;
    @Autowired
    private ErpBackRecordMapper erpBackRecordMapper;
    @Autowired
    private SoMasterServiceImpl soMasterService;
    @Autowired
    private PushErpService pushErpService;
    @Autowired
    private SoDetailService soDetailService;
    @Autowired
    private AsnMasterService asnMasterService;
    @Autowired
    private WaveDetailService waveDetailService;
    @Autowired
    private WaveMasterService waveMasterService;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private ErpPushLogService erpPushLogService;

    @Autowired
    private OutDetailService outDetailService;
    @Autowired
    private OutMasterService outMasterService;

    @Autowired
    private ErpPushLogInfoService erpPushLogInfoService;

    @Autowired
    private PickTaskService pickTaskService;
    @Autowired
    private StrategyErpService strategyErpService;

    @Autowired
    private AsyncService asyncService;

    @Autowired
    private TransferBillService transferBillService;

    @Autowired
    private AcceptRecordService acceptRecordService;

    @Autowired
    private AsnCodeDetailService asnCodeDetailService;

    @Autowired
    private StrategyEnterService strategyEnterService;


    @Override
    public List<TransferBill> saveAndConfirmTransferBill(List<TransferBill> transferBills) {
        List<TransferBill> list = this.createTransferBill(transferBills);
        // 这里直接装箱单确认了
        return this.confirmTransferBill(list);
    }

    @Override
    public List<TransferBill> createTransferBill(List<TransferBill> transferBills) {
        for (TransferBill transferBill : transferBills) {
            //Step1.各类数据数据校验，不合法给与异常信息提示
            //仓库 来源库位  目标库位  来源容器  目标容器  物料  批次
            this.validateAndPrepareTransferData(transferBill);

            //Step2.组装收货单数据
            //单据号
            transferBill.setTransferBillCode(codeRuleService.generateCode(SystemManageConstant.CODE_RULE_TRANS));
            //状态
            transferBill.setState(InStockConstant.TRANS_STATE_INIT);
        }
        //Step3.统一保存
        this.saveBatch(transferBills);

        return transferBills;
    }


    @Override
    public List<TransferBill> confirmTransferBill(List<TransferBill> transferBills) {
        for (TransferBill transferBill : transferBills) {
            //Step1.判断转移单是否满足确认的条件 修改状态
            if (ObjectUtil.notEqual(InStockConstant.TRANS_STATE_INIT, transferBill.getState())) {
                throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "转移单不为新建状态，不可确认!");
            }
            transferBill.setState(InStockConstant.TRANS_STATE_FINISHED);
            transferBill.setConfirmTime(DateUtil.now());
            //Step2.生成库存事务请求 并提交(事务提交，修改库存)
            InventoryTransact inventoryTransact = this.toStockRequest(transferBill);
            inventoryTransactService.run(inventoryTransact);
        }
        //Step3.批次保存转移单
        this.saveOrUpdateBatch(transferBills);
//        if(true) {throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "xx");}
        return transferBills;
    }

    /**
     * 校验转移单的各类数据是否合法
     *
     * @param transferBill 转移单
     */
    private void validateAndPrepareTransferData(TransferBill transferBill) {


        //仓库
        WareInfo wareInfo = wareInfoService.getOneByField("ware_id", transferBill.getWareId());
        Preconditions.checkNotNull(wareInfo, "根据仓库id[%s]获取仓库失败!", new Object[]{transferBill.getWareId()});
        transferBill.setWareCode(wareInfo.getWareCode());
        transferBill.setWareName(wareInfo.getWareName());
        //来源库位 所有类型都需要校验
        CellInfo fromCellInfo = cellInfoService.findByCodeAndWareId(transferBill.getFromCellCode(), transferBill.getWareId());
        Preconditions.checkNotNull(fromCellInfo, "根据仓库id[%s],库位[%s]获取来源库位失败!", new Object[]{transferBill.getWareId(), transferBill.getFromCellCode()});
        //目标库位
        //上架，转移，拣货 需要校验
        CellInfo toCellInfo = cellInfoService.findByCodeAndWareId(transferBill.getToCellCode(), transferBill.getWareId());
        Preconditions.checkNotNull(toCellInfo, "根据仓库id[%s],库位[%s]获取目标库位失败!", new Object[]{transferBill.getWareId(), transferBill.getToCellCode()});
        //物料
        ItemInfo itemInfo = itemInfoService.getOneByField("item_code", transferBill.getItemCode());
        Preconditions.checkNotNull(itemInfo, "根据物料编码[%s]获取物料失败!", new Object[]{transferBill.getItemCode()});
        transferBill.setItemName(itemInfo.getItemName());
//        transferBill.setPackDetailId(itemInfo.getPackCode());
        //批次
//        ItemBatch itemBatch = itemBatchService.getOneByField("batch_name", transferBill.getBatchName());
//        Preconditions.checkNotNull(itemBatch, "根据物料[%s],批次号[%s]获取批次失败!", new Object[]{transferBill.getItemCode(), transferBill.getBatchName()});
//        transferBill.setBatchId(itemBatch.getBatchId());
//        transferBill.setBatchName(itemBatch.getBatchName());
        //来源容器
        //上架 转移 拣货 分拣 。
        if (ObjectUtil.notEqual(InStockConstant.TRANS_TYPE_PACK_BOX, transferBill.getBillType())) {
            if (StringUtils.isEmpty(transferBill.getFromBoxCode())) {
                throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "来源容器不允许为空");
            }
        }

        //TODO: 库存确认
        //目标容器
        //需要有目标容器：装箱 分拣
//        if (InStockConstant.TRANS_TYPE_PACK_BOX.equals(transferBill.getBillType()) || InStockConstant.TRANS_TYPE_PICK2.equals(transferBill.getBillType())) {
//            if (StringUtils.isEmpty(transferBill.getToBoxCode())) {
//                throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "目标容器不允许为空");
//            }
//        } else {
//            //不能有目标容器：上架 转移 拣货
//            if (StringUtils.isNotEmpty(transferBill.getToBoxCode())) {
//                throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "不允许有目标容器");
//            }
//        }
    }

    private InventoryTransact toStockRequest(TransferBill transferBill) {
        InventoryTransact inventoryTransact = new InventoryTransact();
        //Step1.准备数据
        //仓库
        inventoryTransact.setWareId(transferBill.getWareId());
        inventoryTransact.setWareName(transferBill.getWareName());
        //库位
        inventoryTransact.setFromCellCode(transferBill.getFromCellCode());
        inventoryTransact.setToCellCode(transferBill.getToCellCode());
        //容器
        inventoryTransact.setFromBoxCode(transferBill.getFromBoxCode());
        inventoryTransact.setToBoxCode(transferBill.getToBoxCode());
        //物料
        inventoryTransact.setItemCode(transferBill.getItemCode());
        inventoryTransact.setItemName(transferBill.getItemName());
        //批次
        inventoryTransact.setFromBatchId(transferBill.getBatchId());
        inventoryTransact.setFromBatchName(transferBill.getBatchName());
        inventoryTransact.setToBatchId(transferBill.getBatchId());
        inventoryTransact.setToBatchName(transferBill.getBatchName());
        //数量
        inventoryTransact.setToQuantity(transferBill.getQty().doubleValue());
        //包装 转换率
        inventoryTransact.setFromPackDetailId(transferBill.getPackDetailId());
        inventoryTransact.setToPackDetailId(transferBill.getPackDetailId());
        inventoryTransact.setToTransRatio(new Double(1));
        inventoryTransact.setFromTransRatio(new Double(1));
        //创建人 时间
        inventoryTransact.setCreateUserId(transferBill.getConfirmUserId());
        inventoryTransact.setCreateUserName(transferBill.getConfirmUserName());
        inventoryTransact.setCreateTime(DateUtil.now());
        //事务类型
        inventoryTransact.setTransactType(handleTransactType(transferBill.getBillType()));
        //来源单据号
        inventoryTransact.setBillNo(transferBill.getTransferBillCode());
        //冻结标识
        inventoryTransact.setState(transferBill.getFreezeFlag());
        inventoryTransact.setAsnStockId(transferBill.getAsnStockId());
        inventoryTransact.setAsnStockName(transferBill.getAsnStockName());


        //单号，详情单号
        inventoryTransact.setBillNo(transferBill.getUda1());
        inventoryTransact.setDetailNo(transferBill.getUda2());
        //库存id
        inventoryTransact.setToInventoryId(transferBill.getInventoryId());

        //Step2.保存，返回
        inventoryTransactService.save(inventoryTransact);
        return inventoryTransact;
    }

    /**
     * 转移单类型到库存类型的转换
     *
     * @param billType 转移单类型
     * @return 库存事物类型
     */
    private Integer handleTransactType(Integer billType) {
        Integer transactType = null;
        switch (billType) {
            case 0: //InStockConstant.TRANS_TYPE_PACK_BOX
                transactType = InventoryConstant.TRANSACT_TYPE_PACK;
                break;
            case 2: //InStockConstant.TRANS_TYPE_UPPER
                transactType = InventoryConstant.TRANSACT_TYPE_UP;
                break;
            case 4: //InStockConstant.TRANS_TYPE_MOVE
                transactType = InventoryConstant.TRANSACT_TYPE_MOVE;
                break;
            case 6: //InStockConstant.TRANS_TYPE_PICK
                transactType = InventoryConstant.TRANSACT_TYPE_PICK;
                break;
//            case 8: //InStockConstant.TRANS_TYPE_PICK2
//                transactType = InventoryConstant.TRANSACT_TYPE_PACK;-
//                break;
            default:
                throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "未匹配到转移单类型");
        }
        return transactType;
    }

    @Override
    public List<TransferBill> selectBillList(TransferBillCriteria transferBillCriteria) {
        // 返回查询的数据
        return transferBillMapper.selectBillList(transferBillCriteria);
    }


    @Override
    @Transactional
    public void saveBillOutInfo(Map<String, Object> map) {
        //Step0.准备数据
        Integer wareId = 285;
        List<WareInfo> wareInfoList = wareInfoService.list();
        Map<Integer, List<WareInfo>> wareMap = wareInfoList.stream().collect(Collectors.groupingBy(WareInfo::getWareId));
        List<Integer> notBillNums = Arrays.asList(82, 251300022, 251300022, 251300058, 200000013);
        List<SoMaster> soMasters = new ArrayList<>();
        List<SoDetail> soDetailList = new ArrayList<>();
        List<BillOutDetailBO> billOutDetailBOS = new ArrayList<>();
        List<BillOutBO> oldPo = pushErpService.OutSourceBill(map);
        if (ObjectUtil.isEmpty(oldPo)) {
            return;
        }
        //去重
        List<BillOutBO> po = distinct(oldPo, BillOutBO::getBillNo);
//        asnMap.put("billIds", billNo);
//        asnMasterService.savePurchaseOrder(asnMap);
        //Step2.表头字段遍历到表体中
        po.stream().map(item -> {
            //表体履约号放在表头中
            item.setAgreementNo(item.getDetails().get(0).getAgreementNo());
            item.setDetails(soMasterService.insertBillNo(item));
            billOutDetailBOS.addAll(item.getDetails());
            return item;
        }).collect(Collectors.toList());


        //Step3.过滤入库类型单据生成入库任务
        List<BillOutBO> poList = po.stream().filter(item -> notBillNums.contains(item.getBillTypeId())).collect(Collectors.toList());

        asnMasterService.saveOrder(poList);

        //Step4.订单号去重
        Set<String> oldBillNos = po.stream().map(BillOutBO::getBillNo).collect(Collectors.toSet());
        List<String> orderBillNo = po.stream().map(BillOutBO::getOrderBillNo).collect(Collectors.toList());
        List<SoMaster> orderSo = soMasterService.list(new QueryWrapper<SoMaster>().in("order_bill_no", orderBillNo));
        //过滤反下达单子
//        this.updateOrder(orderSo, po);

        if (ObjectUtil.isEmpty(oldBillNos)) {
            return;
        }

        //Step5.根据订单号过滤表里面已经有的数据(过滤)
        List<SoMaster> soMasterList = soMasterService.list(new QueryWrapper<SoMaster>().in("bill_no", oldBillNos));


        Set<String> newBillNos = soMasterList.stream().map(SoMaster::getBillNo).collect(Collectors.toSet());
        //过滤 82, 251300022, 251300022, 251300058, 200000013 出库单据类型
        List<BillOutBO> billOutBOS = soMasterService.filterBillOut(po, newBillNos, notBillNums);

        //先发配件，通用件调拨
        List<Integer> categoryIds = Arrays.asList(542814, 559967);
        //先发配件542814
        List<BillOutBO> billOutBOList = po.stream().filter(item -> categoryIds.contains(item.getCategoryId())).collect(Collectors.toList());
        this.first(billOutBOList);
        List<BillOutDetailBO> billOutDetailBOS1 = soMasterService.filterDetaiBo(billOutDetailBOS, newBillNos, notBillNums);

        if (ObjectUtil.isEmpty(billOutBOS) && ObjectUtil.isEmpty(billOutDetailBOS1)) {
            return;
        }


        //Step6.获取所有物料
        Set<String> itemNumbers = billOutDetailBOS1.stream().map(BillOutDetailBO::getItemNumber).collect(Collectors.toSet());
        //获取所有物料
        List<ItemInfo> itemInfoList = itemInfoService.list(new QueryWrapper<ItemInfo>().in("item_code", itemNumbers));
        Map<String, List<BillOutDetailBO>> detailMap = billOutDetailBOS1.stream().collect(Collectors.groupingBy(BillOutDetailBO::getBillNo));


        //标准件
        List<String> notCategory = Arrays.asList("标准件", "标准件-MRP物料", "辅料-MRP物料", "辅料");
        //Strep7.红蓝字对冲,同一单号,不同的类型 入库出库数量对冲
        List<BillOutDetailBO> merge = soMasterService.merge(detailMap);
        Map<String, ItemInfo> itemInfoMap = convertMap(itemInfoList, ItemInfo::getItemCode);

        //Step
        Set<String> detailBillNo = new HashSet<>();
        for (BillOutDetailBO billOutDetailBO : merge) {
            ItemInfo itemInfo = itemInfoMap.get(billOutDetailBO.getItemNumber());
            //获取发料属性
            String feedCateGory = Optional.ofNullable(itemInfo).map(item -> item.getFeedCategory()).orElse("");
            //生产领料 通用件
            if (notCategory.contains(feedCateGory) && billOutDetailBO.getTargetBillTypeId() == 24) {
                continue;
            }
            SoDetail soDetail = new SoDetail();
            soDetail.setBillNo(billOutDetailBO.getBillNo());
            if (billOutDetailBO.getItemNumber().equals("8S078404AA")) {
                System.out.println("11111");
            }
            ;
            soDetail.setStockId(billOutDetailBO.getStockId());
            soDetail.setErpBillId(billOutDetailBO.getSourceBillId());
            soDetail.setBomSplit(billOutDetailBO.getRowIndex());//行号
            soDetail.setAllotPackDetailId(billOutDetailBO.getItemId());//物料ID
            soDetail.setItemCode(billOutDetailBO.getItemNumber());//物料编码
            soDetail.setItemName(billOutDetailBO.getItemName());//物料名称
            soDetail.setSpec(billOutDetailBO.getItemModel());//规格型号
            soDetail.setPackDetailId(33469);//辅助属性类别ID
            soDetail.setModel(billOutDetailBO.getAuxPropName());//辅助属性
            //批次管理
            soDetail.setPackDescribe(billOutDetailBO.getBatchManager() == null || billOutDetailBO.getBatchManager() == false ? "0" : "1");
            soDetail.setDetailNo(billOutDetailBO.getBillNo() + "-" + billOutDetailBO.getRowIndex());//批号
            soDetail.setPackDetailId(billOutDetailBO.getUnitId());//基本单位ID
            soDetail.setSoUdfDs2(billOutDetailBO.getUnitName());//单位
            soDetail.setOrderQuantity(billOutDetailBO.getOriginQty());//基本单位数量
            soDetail.setAllottedQuantity(billOutDetailBO.getOriginQty() - billOutDetailBO.getQty());
            soDetail.setPickQuantity(billOutDetailBO.getOriginQty() - billOutDetailBO.getQty());
            soDetail.setDeliveryQuantity(billOutDetailBO.getOriginQty() - billOutDetailBO.getQty());
            soDetail.setMergeNo(billOutDetailBO.getAgreementNo());
//                                soDetail.setAllotPackDescribe(billOutDetailBO.getPlanModeId().toString());//计划模式ID
            soDetail.setSoUdfDs3(billOutDetailBO.getMtoNo());//计划跟踪号
            soDetail.setMemo(billOutDetailBO.getRemark());//备注
            soDetail.setPickPackDescribe(billOutDetailBO.getTargetBillTypeId().toString());//目标单据类型ID
            //目标单据红蓝字
            soDetail.setRob(billOutDetailBO.getTargetBillROB());
            soDetail.setTransRatio(1.00);
            soDetail.setRemark(billOutDetailBO.getRemark());
            soDetailList.add(soDetail);
//            }

        }
        List<DataDictDetail> dataDictDetails = dataDictDetailService.list(new QueryWrapper<DataDictDetail>().eq("data_dict_code", "else"));
        Map<String, DataDictDetail> dataDictDetailMap = convertMap(dataDictDetails, DataDictDetail::getDictKey);


        Integer i = 0;
        //新增任务
        for (BillOutBO billOutBO : billOutBOS) {

            SoMaster soMaster = new SoMaster();
            soMaster.setCreateTime(DateUtils.getNowDateTimeString());
            soMaster.setOrganizationId(86);//货主id
            soMaster.setWareId(wareId);//仓库id
            soMaster.setCategoryId(billOutBO.getCategoryId()); //其他出库类别id
            soMaster.setWareCode(wareMap.get(wareId).get(0).getWareCode());
            soMaster.setWareName(wareMap.get(wareId).get(0).getWareName());
            soMaster.setSupplierId(billOutBO.getSupplierId());//供应商id
            soMaster.setSupplierName(billOutBO.getSupplierName()); // 供应商名称
            soMaster.setOrderBillNo(billOutBO.getOrderBillNo()); //订单号
            soMaster.setBeforeNum(billOutBO.getId());

            soMaster.setSoType(detailMap.get(billOutBO.getBillNo()).iterator().next().getTargetBillTypeId());
            //单据数量
            soMaster.setSoQty(soMasterService.sumSoQty(billOutDetailBOS1, billOutBO.getBillNo()));
            //出库数量
            soMaster.setQcQty(soMasterService.sumQcQty(billOutDetailBOS1, billOutBO.getBillNo()));
//                            soMaster.setCreateUserName(billOutBO.getBillTypeId().toString()); //单据类型id
            soMaster.setBillType(billOutBO.getBillTypeId()); //单据类型id
//                            soMaster.setWareCode(billOutBO.getBillTypeName());//单据类型名称
            soMaster.setSoTypeName(billOutBO.getBillTypeName());//单据类型名称
            soMaster.setTradeNo(billOutBO.getAgreementNo());  //履约号
            soMaster.setBillNo(billOutBO.getBillNo());//单据编号
            soMaster.setShipCode(billOutBO.getBillDate());//单据日期
            //工业单据状态 0 - 草稿 1 - 已审核，未关联 2 - 已审批，部分关联 3 - 已审批，全部关联 生产任务单据状态 0 - 计划 5 - 确认 1 - 下达 3 - 结案 BOS单据状态 2 - 未审核 4 - 审核中 16 - 已审核
            soMaster.setCarrierId(billOutBO.getBillStatus());//工业单据状态
            soMaster.setIsClose(billOutBO.getBillClosed() == null || billOutBO.getBillClosed() == false ? 0 : 1);//关闭状态
            soMaster.setOrganizationId(-1);
            soMaster.setOrganizationName("自有");
            soMaster.setOrganizationCode("SYS_MINE");
            soMaster.setOrderBillId(billOutBO.getOrderBillId());
            soMaster.setDeptId(billOutBO.getDeptId());//部门ID
            soMaster.setDeptName(billOutBO.getDeptName());//部门名称
            soMaster.setMemo(detailMap.get(billOutBO.getBillNo()).iterator().next().getRemark());//备注
            soMaster.setExpectTimeFm(billOutBO.getPlanStartDate());//计划开工日期
            soMaster.setCustomerId(billOutBO.getCustomerId());//客户ID
            soMaster.setCustomerName(billOutBO.getCustomerName());//客户名称
            if (soMaster.getSoType() == 28) {
                soMaster.setDeptId(641821);
                soMaster.setDeptName("配网车间");
            }

            //新增
            soMasters.add(soMaster);
        }
        //批量新增
        soMasterService.different(billOutBOS);
        //合并物料编码一样的单据,物料编码一样的数量++
        //批量新增 soMaster
        soMasterService.saveBatch(soMasters);
        //批量新增 详情
        soDetailService.saveBatch(soDetailList);

        log.info("拉去数量{}" + po.size() + "插入数量" + soMasters.size() + "入库数量" + poList.size() + "标准件数量" + i + "库存单子" + soMasterList.size());
        //执行拣货任务
//        throw  new ServiceException(CommonCode.SERVER_INERNAL_ERROR,"该库存码无效！");

    }


//    public void sendErp(List<SoMaster> soMasters) {
//        List<String> billNos = soMasters.stream().map(SoMaster::getBillNo).collect(Collectors.toList());
//        List<SoDetail> soDetails = soDetailService.list(new QueryWrapper<SoDetail>()
//                .in("bill_no", billNos)
//        );
//        List<String> itemCodes = soDetails.stream().map(SoDetail::getItemCode).collect(Collectors.toList());
//
//
//
//    }

    public void first(List<BillOutBO> po) {
        if (ObjectUtil.isEmpty(po)) {
            return;
        }
        List<AsnMaster> asnMasters = new ArrayList<>();
        List<AsnDetail> asnDetails = new ArrayList<>();

        Integer wareId = 285;
        List<WareInfo> wareInfoList = wareInfoService.list();
        Map<Integer, WareInfo> wareMap = wareInfoList.stream().collect(Collectors.toMap(WareInfo::getWareId, item -> item, (oldValue, newValue) -> newValue));
        Set<String> billNos = po.stream().map(BillOutBO::getBillNo).collect(Collectors.toSet());
        List<AsnMaster> oldAsnMaster = asnMasterService.list(new QueryWrapper<AsnMaster>().in("bill_no", billNos));
        Map<String, AsnMaster> asnMap = oldAsnMaster.stream().collect(Collectors.toMap(AsnMaster::getBillNo, asnMaster -> asnMaster, (oldValue, newValue) -> newValue));
        for (BillOutBO bo : po) {
            if (ObjectUtil.isEmpty(asnMap.get(bo.getBillNo()))) {
                AsnMaster asnMaster = new AsnMaster();
                //仓库id
                asnMaster.setWareId(wareId); //仓库id
                asnMaster.setWareCode(wareMap.get(wareId).getWareCode()); //仓库编码
                asnMaster.setWareName(wareMap.get(wareId).getWareName()); //仓库名称
                asnMaster.setOrganizationId(-1);
                asnMaster.setOrganizationName("自有");
                asnMaster.setOrganizationCode("SYS_MINE");
                asnMaster.setCategoryId(bo.getCategoryId());
                asnMaster.setBillSource(0);
                asnMaster.setUda1(bo.getBillTypeName());//单据类型
                asnMaster.setBillNo(bo.getBillNo());//单据编号
                asnMaster.setSupplierId(bo.getSupplierId());//供应商ID
                asnMaster.setSupplierName(bo.getSupplierName());//供应商名称
                asnMaster.setCreateUserId(bo.getCustomerId());//客户ID
                asnMaster.setAsnUdfHs2(bo.getCustomerName());//客户名称
                asnMaster.setDeptId(bo.getDeptId());//部门ID
                asnMaster.setUda3(bo.getDeptName());//部门名称
                asnMaster.setMemo(bo.getRemark());//备注
                asnMaster.setAgreementNo(bo.getDetails().iterator().next().getAgreementNo()); //履约号
                asnMaster.setAsnType(10); //入库单类型1,2,5,10,41
                List<BillOutDetailBO> details = bo.getDetails();
                Integer i = 1;
                for (BillOutDetailBO purchaseOrderDetailBO : details) {
                    AsnDetail asnDetail = new AsnDetail();
                    //MTo号
                    asnDetail.setMtoNo(purchaseOrderDetailBO.getAgreementNo());
                    asnDetail.setRowIndex(purchaseOrderDetailBO.getRowIndex());
                    asnDetail.setBillNo(asnMaster.getBillNo());//ASN单号
                    asnDetail.setPackDetailId(33469);//基本单位ID
                    asnDetail.setPackDescribe(purchaseOrderDetailBO.getUnitName());//单位
                    asnDetail.setExpectPackDetailId(purchaseOrderDetailBO.getItemId());//物料ID
                    asnDetail.setItemCode(purchaseOrderDetailBO.getItemNumber());//物料编码
                    asnDetail.setItemName(purchaseOrderDetailBO.getItemName());//物料名称
                    asnDetail.setUda1(purchaseOrderDetailBO.getItemModel());//规格型号
                    asnDetail.setAcceptPackDetailId(purchaseOrderDetailBO.getAuxPropClassId());//辅助属性类别ID
                    asnDetail.setUpperPackDetailId(purchaseOrderDetailBO.getAuxPropId());//辅助属性ID
                    asnDetail.setAsnUdfDs1(purchaseOrderDetailBO.getAuxPropName());//辅助属性
                    asnDetail.setDetailNo(asnMaster.getBillNo() + "-" + i);
                    asnDetail.setMemo(purchaseOrderDetailBO.getRemark());
                    asnDetail.setUda2(purchaseOrderDetailBO.getBatchManager() == null || purchaseOrderDetailBO.getBatchManager() == false ? "0" : "1");
                    asnDetail.setExpectQuantity(purchaseOrderDetailBO.getQty());//基本单位数量
                    i++;
                    asnDetails.add(asnDetail);
                }
                asnMasters.add(asnMaster);
            }

        }
        asnMasterService.saveBatch(asnMasters);
        asnDetailService.saveBatch(asnDetails);

    }


    public void updateOrder(List<SoMaster> orderSo, List<BillOutBO> po) {
        Map<String, List<SoMaster>> map = orderSo.stream().collect(Collectors.groupingBy(SoMaster::getOrderBillNo));
        for (BillOutBO billOutBO : po) {
            if (billOutBO.getBillTypeId() != 24) {
                continue;
            }
            if (("225438-91").equals(billOutBO.getOrderBillNo())) {
                System.out.println("11111");
            }
            List<SoMaster> soMasters = map.get(billOutBO.getOrderBillNo());
            if (ObjectUtil.isEmpty(soMasters)) {
                continue;
            }
            if (soMasters.size() > 1) {
                Set<Integer> ids = soMasters.stream().map(SoMaster::getSoMasterId).collect(Collectors.toSet());
                List<SoMaster> soMasterList = soMasterService.listByIds(ids);
                List<String> billNos = soMasterList.stream().map(SoMaster::getBillNo).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(billNos)) {
                    soDetailService.remove(new QueryWrapper<SoDetail>().in("bill_no", billNos));
                }
                soMasterService.removeByIds(ids);
            }
            SoMaster soMaster = soMasters.iterator().next();
            //如果原单跟新单子不相等，删除原单
            if (!billOutBO.getBillNo().equals(soMaster.getBillNo())) {
                soDetailService.remove(new QueryWrapper<SoDetail>().in("bill_no", soMaster.getBillNo()));
                soMasterService.removeById(soMaster.getSoMasterId());
            }

        }
    }


    /**
     * 直发虚仓出库
     *
     * @param id
     * @param vmiNumber
     */
    @Override
    @Transactional
    public void virtual(Long id, CurrentUser currentUser, Double vmiNumber) {

        List<OutDetail> outSet = new ArrayList<>();
        WaveDetail waveDetail = waveDetailService.getById(id);
        waveDetail.setState(1);  //1已分配
        List<Inventory> inventorieUpdate = new ArrayList<>();
        //待出库的所有物料
        List<SoDetail> soDetailList = soDetailService.list(new QueryWrapper<SoDetail>().in("wave_detail_id", id));
        //获取可出库的库存
        List<Inventory> inventoryList = inventoryService.list(new QueryWrapper<Inventory>()
                .in("item_code", waveDetail.getItemCode())
                //直发虚仓仓库id待定
                .and(w -> w
                        //直发虚仓
                        .or().notIn("asn_stock_id", directId)
                        .or().isNull("asn_stock_id")
                )
                .notIn("cell_code", 285000, 285333)
        );
        //物料编码分组
        Map<String, List<Inventory>> inventoryMap = inventoryList.stream().collect(Collectors.groupingBy(Inventory::getItemCode));

        //获取待出库所有物料
        List<SoDetail> soDetails = subSoDetailAndPush(soDetailList, vmiNumber);

        for (SoDetail soDetail : soDetails) {
            OutDetail outDetail = new OutDetail();
            List<Inventory> inventories = inventoryMap.get(waveDetail.getItemCode());
            for (Inventory inv : inventories) {
                double invQty = inv.getQuantity() - inv.getAllotQuantity() - inv.getFreezeQuantity();
                if (soDetail.getSubQty() <= 0) {
                    break;
                }
                //如果库存不够分配
                if (invQty <= soDetail.getSubQty()) {
                    BeanUtils.copyProperties(soDetail, outDetail);
                    outDetail.setDeliveryQuantity(soDetail.getSubQty());
                    outDetail.setBoxCode(inv.getBoxCode());
                    outDetail.setCellCode(inv.getCellCode());
                    outDetail.setBatchName(inv.getBatchName());
                    outDetail.setErpAreaId(inv.getErpAreaId());
                    outSet.add(outDetail);
                    //可出库数量
                    soDetail.setSubQty(soDetail.getSubQty() - invQty);
//                    vmiNumber -= invQty;
                    inventorieUpdate.add(inv);
                } else {
                    //库存足够分配，全部填满SO的数量
                    BeanUtils.copyProperties(soDetail, outDetail);
                    outDetail.setDeliveryQuantity(soDetail.getSubQty());
                    outDetail.setBoxCode(inv.getBoxCode());
                    outDetail.setCellCode(inv.getCellCode());
                    outDetail.setBatchName(inv.getBatchName());
                    outDetail.setErpAreaId(inv.getErpAreaId());
                    outSet.add(outDetail);
                    //扣减已分配的库存数量
                    inv.setAllotQuantity(inv.getAllotQuantity() + soDetail.getSubQty());
                    break;
                }
            }
            //批量修改库存数量
            inventoryService.updateBatchById(inventories);
        }

        soDetailService.updateBatchById(soDetails);
        waveDetailService.updateState(waveDetail, vmiNumber);


        asyncService.asyncPushErp(inventorieUpdate, outSet, currentUser);
    }

    /**
     * 获取可出库数据源出库
     *
     * @param soDetails
     * @param subNumber
     */
    public List<SoDetail> subSoDetailAndPush(List<SoDetail> soDetails, Double subNumber) {
        List<SoDetail> soDetailList = new ArrayList<>();
        for (SoDetail soDetail : soDetails) {
            //待分配数量
            double soQty = soDetail.getOrderQuantity() - soDetail.getAllottedQuantity();
            if (soQty == 0.00) {
                continue;
            }
            if (soQty >= subNumber) {
                soDetail.setSubQty(subNumber);
                //增加分配数量
                soDetail.setAllottedQuantity(subNumber + soDetail.getAllottedQuantity());
                //增加拣货数量
                soDetail.setPickQuantity(soDetail.getPickQuantity() + subNumber);
                //增加复核数量
                soDetail.setDeliveryQuantity(soDetail.getDeliveryQuantity() + subNumber);
                soDetailList.add(soDetail);
                break;
            } else {
                soDetail.setPickQuantity(soDetail.getPickQuantity() + soQty);
                soDetail.setAllottedQuantity(soDetail.getAllottedQuantity() + soQty);
                soDetail.setDeliveryQuantity(soDetail.getDeliveryQuantity() + soQty);
                //指向改为空
                soDetail.setSubQty(soQty);
                soDetailList.add(soDetail);
                subNumber -= soQty;
            }
        }
        return soDetailList;
    }


    /**
     * 直发虚仓出库
     *
     * @param soDetail
     * @param currentUser
     */
    @Override
    public void virtualSoDetail(SoDetail soDetail, CurrentUser currentUser) {
        List<OutDetail> outSet = new ArrayList<>();
        Set<SoDetail> set = new HashSet<>();
        List<Inventory> inventorieUpdate = new ArrayList<>();

        String itemCode = soDetail.getItemCode();

        List<Inventory> inventoryList = inventoryService.list(new QueryWrapper<Inventory>()
                .in("item_code", itemCode)
                //直发虚仓仓库id待定
                .in("asn_stock_id", 1111427)
                .ne("cell_code", 285000)
                .ne("cell_code", 285333)
                .eq("asn_stock_name", "直发待检仓")
        );
        Map<String, List<Inventory>> inventoryMap = inventoryList.stream().collect(Collectors.groupingBy(Inventory::getItemCode));
        OutDetail outDetail = new OutDetail();
        //带填补数量
        double soQty = soDetail.getOrderQuantity() - soDetail.getDeliveryQuantity();
        if (soQty == 0) {
            return;
        }
        List<Inventory> inventories = inventoryMap.get(soDetail.getItemCode());
        double allottedQuantity = 0.00;
        for (Inventory inv : inventories) {
            double invQty = inv.getQuantity() - inv.getAllotQuantity() - inv.getFreezeQuantity();
            if (invQty <= soQty) {
                soDetail.setDeliveryQuantity(soDetail.getDeliveryQuantity() + invQty);
                soDetail.setState(WareTaskConstant.SO_DETAIL_STATE_PART_SEND);
                set.add(soDetail);
                BeanUtils.copyProperties(soDetail, outDetail);
                outDetail.setBoxCode(inv.getBoxCode());
                outDetail.setCellCode(inv.getCellCode());
                outDetail.setBatchName(inv.getBatchName());
                outDetail.setErpAreaId(inv.getErpAreaId());
                outSet.add(outDetail);
                allottedQuantity += invQty;
                inv.setAllotQuantity(inv.getAllotQuantity() + invQty);
                inventorieUpdate.add(inv);
            } else {
                if (soQty == 0) {
                    break;
                }
                //库存足够分配，全部填满SO的数量
                soDetail.setDeliveryQuantity(soQty);
                soDetail.setState(WareTaskConstant.SO_DETAIL_STATE_ALL_SEND);
                BeanUtils.copyProperties(soDetail, outDetail);
                outDetail.setBoxCode(inv.getBoxCode());
                outDetail.setCellCode(inv.getCellCode());
                outDetail.setBatchName(inv.getBatchName());
                outDetail.setErpAreaId(inv.getErpAreaId());
                outSet.add(outDetail);
                set.add(soDetail);
                //扣减已分配的库存数量
                inv.setAllotQuantity(inv.getAllotQuantity() + soQty);
                allottedQuantity += soDetail.getOrderQuantity();
                inventorieUpdate.add(inv);
            }
            //修改库存数量
        }


        asyncService.asyncPushErp(inventorieUpdate, outSet, currentUser);
    }


    /**
     * 转移
     *
     * @param
     * @param id
     */
    @Override
    public void updateErpLog(List<ErpPushLogInfo> newData, Integer id) {
        //step1.初始化数据
        ErpPushLog erpPushLog = erpPushLogService.getById(id);
        //如果为调拨单

        ;
        List<ErpPushLogInfo> oldData = erpPushLogInfoService.list(new QueryWrapper<ErpPushLogInfo>().eq("erp_push_id", id));
        Map<Integer, List<ErpPushLogInfo>> infoMap = oldData.stream().collect(Collectors.groupingBy(ErpPushLogInfo::getId));
        List<Inventory> inventoryList = inventoryService.list(new QueryWrapper<Inventory>().in("box_code", oldData.stream().map(ErpPushLogInfo::getBoxCode).collect(Collectors.toSet())));
        //根据容器号分组
        Map<String, List<Inventory>> inventoryMap = inventoryList.stream().collect(Collectors.groupingBy(Inventory::getBoxCode));
        List<TransferBill> transferBills = new ArrayList<>();

        //要增加的物料
        List<ErpPushLogInfo> add = new ArrayList<>();
        //减少的物料  生成转移单
        List<ErpPushLogInfo> minus = new ArrayList<>();
        for (ErpPushLogInfo newDatum : newData) {
            ErpPushLogInfo erpPushLogInfo = new ErpPushLogInfo();
            if (ObjectUtil.isNotEmpty(infoMap.get(newDatum.getId()))) {
                ErpPushLogInfo next = infoMap.get(newDatum.getId()).iterator().next();
                BeanUtils.copyProperties(newDatum, erpPushLogInfo);
                //如果要修改的数量比原始数量
                if (newDatum.getQty() > next.getQty()) {
                    throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, newDatum.getItemName() + "不能大于原始数量！");
                }
                if (newDatum.getQty() <= next.getQty()) {
                    erpPushLogInfo.setQty(next.getQty() - newDatum.getQty());
                    minus.add(erpPushLogInfo);
                }
            }
        }


        List<ErpPushLogInfo> infos = newData.stream().filter(item -> ObjectUtil.isNotEmpty(item.getClose()) && !item.getClose()).collect(Collectors.toList());
        List<ErpPushLogInfo> pushLogInfos = newData.stream().filter(item -> ObjectUtil.isNotEmpty(item.getClose()) && item.getClose()).collect(Collectors.toList());
        this.merge(minus, inventoryMap, inventoryList, transferBills, true);
        this.merge(infos, inventoryMap, inventoryList, transferBills, false);
        this.saveBatch(transferBills); //生成转移单
        inventoryService.updateBatchById(inventoryList); //处理库存
        ;
        Map<String, String> map = pushErpService.twiceSend(this.getBean(erpPushLog, pushLogInfos));
        String code = map.get("code");
        String msg = map.get("msg");
        if (!"200".equals(code)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, map.get("msg"));
        }
        erpPushLog.setCode(code);
        erpPushLog.setMsg(msg);
        erpPushLogService.updateById(erpPushLog);
    }

    /**
     * @param criteria
     * @return
     */
    @Override
    public List<AsnMaster> alignList(DispatCriteria criteria) {
        return baseMapper.alignList(criteria);
    }

    /**
     * 详情
     *
     * @param billNo
     * @return
     */
    @Override
    public List<SoDetail> detail(String billNo) {
        if (ObjectUtil.isEmpty(billNo)) {
            return null;
        }

        List<String> billNos = new ArrayList<>();
        String[] bills = billNo.split("\\s+");
        for (String newBillNo : bills) {
            billNos.add(newBillNo.trim());
        }
        List<SoDetail> soDetailList = soDetailService.findByOrderNo(billNos);

        return soDetailService.lendDetail(soDetailList);
    }

    /**
     * 查其他生产任务单中的数据
     *
     * @param contrastVo@return
     */
    @Override
    public List<SoDetail> beBeing(ContrastVo contrastVo) {
        return soDetailService.beBeing(contrastVo);
    }

    /**
     * 齐套提交
     *
     * @param soDetailVo
     */
    @Override
    public void dispatch(SoDetailVo soDetailVo) {
        Integer areaId = 63662;
        SoDetail leftDetail = soDetailVo.getLeftDetail();
        List<OutDetail> newDetails = new ArrayList<>();
        List<OutDetail> outDetails = new ArrayList<>();
        List<UpdatePPF> returnList = new ArrayList<>();
        List<UpdatePPF> inputList = new ArrayList<>();

//        借料项
        List<SoDetail> soDetails = soDetailVo.getRightDetail().stream().filter(item -> ObjectUtil.isNotEmpty(item.getNumber())).collect(Collectors.toList());
        //借料项全部数
        double sum = soDetails.stream().mapToDouble(SoDetail::getNumber).sum();
        if (sum == 0) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "借料数量为空");
        }

        List<Inventory> list = new ArrayList<>();

        //红字退库物料
        for (SoDetail soDetail : soDetails) {
            OutDetail outDetail = new OutDetail();
            soDetail.setAllottedQuantity(soDetail.getAllottedQuantity() - soDetail.getNumber());
            soDetail.setPickQuantity(soDetail.getPickQuantity() - soDetail.getNumber());
            soDetail.setDeliveryQuantity(soDetail.getDeliveryQuantity() - soDetail.getNumber());
            soDetail.setAllReturnQuantity(soDetail.getAllReturnQuantity() + soDetail.getNumber());
            BeanUtils.copyProperties(soDetail, outDetail);
            outDetail.setBatchName("999");
            outDetail.setDeliveryQuantity(soDetail.getNumber());
            outDetail.setErpAreaId(areaId);
            outDetails.add(outDetail);
            UpdatePPF updatePPF = new UpdatePPF();
            updatePPF.setBillId(soDetail.getErpBillId());
            updatePPF.setRowIndex(soDetail.getBomSplit());
            updatePPF.setCommitQty(0 - soDetail.getNumber());
            returnList.add(updatePPF);
            Inventory inventory = new Inventory();
            inventory.setItemCode(soDetail.getItemCode());
            inventory.setItemName(soDetail.getItemName());
            inventory.setErpAreaId(areaId);
            inventory.setCellCode(cellInfoService.findErpAreaId(areaId));
            inventory.setBatchName("999");
            inventory.setWareId(285);
            inventory.setWareName("如高高压");
            inventory.setOrganizationName("只有");
            inventory.setOrganizationId(-1);
            inventory.setTransRatio(1.0);
            inventory.setQuantity(soDetail.getNumber());
            list.add(inventory);
        }


        leftDetail.setAllottedQuantity(leftDetail.getAllottedQuantity() + sum);
        leftDetail.setPickQuantity(leftDetail.getPickQuantity() + sum);
        leftDetail.setDeliveryQuantity(leftDetail.getDeliveryQuantity() + sum);
        OutDetail outDetail = new OutDetail();
        UpdatePPF updatePPF = new UpdatePPF();
        updatePPF.setBillId(leftDetail.getErpBillId());
        updatePPF.setRowIndex(leftDetail.getBomSplit());
        updatePPF.setCommitQty(sum);
        inputList.add(updatePPF);
        BeanUtils.copyProperties(leftDetail, outDetail);
        outDetail.setDeliveryQuantity(sum);
        outDetail.setErpAreaId(areaId);
        outDetail.setBatchName("999");
        newDetails.add(outDetail);
        //修改任务单详情
        soDetailService.updateById(leftDetail);
        //批量修改数量
        soDetailService.updateBatchById(soDetails);
        BaseAssist baseAssist = new BaseAssist();
        baseAssist.setRob(false);
        SoMaster soMaster = soMasterService.getOne(new QueryWrapper<SoMaster>().eq("bill_no", soDetails.get(0).getBillNo()));

        /**
         * 修改可分配数量
         */
        try {
            pushErpService.UpdatePPFeedAssignedQty(returnList);
            pushErpService.UpdatePPFeedAssignedQty(inputList);
        } catch (Exception e) {
            System.out.println(e);
        }

        //红字退库
        strategyErpService.resolveSo(soMaster, outDetails, baseAssist);
        //蓝字出库
        try {
            strategyErpService.resolveSo(soMaster, newDetails, new BaseAssist());
        } catch (Exception e) {
            inventoryService.saveBatch(list);
            soDetailService.updateById(leftDetail);
            soDetailService.updateBatchById(soDetails);
        }


    }

    /**
     * 批量装箱
     *
     * @param packBoxData
     * @param currentUser
     */
    @Override
    public void batchCreatePackBox(PackBoxData packBoxData, CurrentUser currentUser) {
        AsnMaster asnMaster = asnMasterService.getOne(new QueryWrapper<AsnMaster>().eq("bill_no", packBoxData.getAcceptRecordCode().trim()).last("limit 1"));
        String cellCode = packBoxData.getCellCode();
        AreaInfo areaByCell = cellInfoService.findAreaByCell(cellCode);
        if (ObjectUtil.isEmpty(areaByCell)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "该库位不存在");
        }

        //Step0. 准备数据
        List<TransferBill> transferBills = new ArrayList<>();
        List<AsnCodeDetail> asnCodeDetails = new ArrayList<>();
        List<AcceptRecord> list = new ArrayList<>();

        //Step1. 获取入库数据明细
        List<String> asnDetailNos = packBoxData.getList().stream()
                .map(item -> item.getAcceptList())
                .flatMap(Collection::stream).collect(Collectors.toList())
                .stream()
                .map(item -> item.getAsnDetailNo()).collect(Collectors.toList());

        List<AsnDetail> asnDetails = asnDetailMapper.selectList(new QueryWrapper<AsnDetail>().in("detail_no", asnDetailNos));

        //Step2.合并详情集合，并累加数量
        //    Step2.1 合并集合详情并Set容器码
        List<AcceptRecord> pushAccept = packBoxData.getList().
                stream().map(item -> {
                    for (AcceptRecord acceptRecord : item.getAcceptList()) {
                        acceptRecord.setBoxCode(item.getBoxCode());
                    }
                    return item.getAcceptList();
                })
                .flatMap(Collection::stream).collect(Collectors.toList());
        Map<Integer, List<AcceptRecord>> acceptMap = pushAccept.stream().collect(Collectors.groupingBy(item -> item.getId()));
        //    Step2.2修改装箱数量
        acceptMap.forEach((id, val) -> {
            AcceptRecord record = acceptMap.get(id).iterator().next();
            double sum = val.stream().mapToDouble(AcceptRecord::getPcs).sum();
            record.setPackedQuantity(record.getPackedQuantity() + sum);
            record.setUpUserId(currentUser.getUserId());
            record.setUpUserName(currentUser.getUserName());
            list.add(record);
        });

        String boxCode = "";
        //Step3. 获取装箱单明细并赋值
        //Step3.1遍历装箱列表
        for (PackBox packBox : packBoxData.getList()) {
            boxCode = packBox.getBoxCode();
            for (AcceptRecord acceptRecord : packBox.getAcceptList()) {
                TransferBill transferBill = new TransferBill();
                transferBill.setItemName(acceptRecord.getItemName());
                //仓库
                transferBill.setWareId(acceptRecord.getWareId());
                //转移单类型
                transferBill.setBillType(InStockConstant.TRANS_TYPE_PACK_BOX);
                //来源库位 收货区库位   无目标库位
                transferBill.setFromCellCode(acceptRecord.getCellCode());
                transferBill.setToCellCode(acceptRecord.getCellCode());
                //asn单号
                transferBill.setUda1(packBoxData.getAcceptRecordCode().trim());
                transferBill.setAsnStockId(acceptRecord.getAsnStockId());
                transferBill.setAsnStockName(acceptRecord.getAsnStockName());
                //无来源容器  目标容器
                transferBill.setToBoxCode(acceptRecord.getBoxCode());
                transferBill.setItemCode(acceptRecord.getItemCode());
                //如果入的是成品库
                if (Convert.toStr(Optional.ofNullable(areaByCell.getWaveType()).orElse(0)).equals("1") && asnMaster.getAsnType() != 41) {

                    transferBill.setBatchName(acceptRecord.getAgreementNo());
                } else {
                    transferBill.setBatchName(acceptRecord.getBatchName());
                }
                transferBill.setPackDetailId(acceptRecord.getPackDetailId());
                transferBill.setQty(new BigDecimal(acceptRecord.getPcs()));
                //单号
                transferBill.setTransferBillCode(codeRuleService.generateCodeByRedis(SystemManageConstant.CODE_RULE_TRANS));
                //状态
                transferBill.setState(InStockConstant.TRANS_STATE_INIT);
                //标记冻结解冻标识
                if (AsnManageConstant.ACCEPT_QC_STATE_TODO.equals(acceptRecord.getQcState())) {
                    //说明是待检的物料
                    transferBill.setFreezeFlag(AsnManageConstant.ACCEPT_QC_STATE_TODO);
                }
                //确认人
                transferBill.setConfirmUserId(currentUser.getUserId());
                transferBill.setConfirmUserName(currentUser.getUserName());
                //收货单编码
                transferBill.setUda2(acceptRecord.getAsnDetailNo());

                acceptRecord.setCategoryId(asnMaster.getCategoryId());

                InventoryTransact inventoryTransact = this.toRequestAccept(acceptRecord, currentUser);
                int inventoryId = inventoryTransactService.run(inventoryTransact);
                transferBill.setInventoryId(inventoryId);
                transferBills.add(transferBill);
            }


        }
        //Step4.新增或修改 装箱单，收货单，详情列表
        transferBillService.saveBatch(transferBills);
        //收货单
        acceptRecordService.updateBatchById(list);
        //详情设计到出库回传
        asnCodeDetailService.saveBatch(asnCodeDetails);
        //如果有库位，则直接上架
        if (ObjectUtil.isNotEmpty(packBoxData.getCellCode())) {
            UpperData upperData = new UpperData();
            QueryWrapper<Inventory> queryWrapper = new QueryWrapper();
            queryWrapper.eq("asn_bill_no", packBoxData.getAcceptRecordCode().trim());
            queryWrapper.eq("box_code", boxCode);
            queryWrapper.eq("cell_code", 285000);
            upperData.setInventories(inventoryService.list(queryWrapper));
            upperData.setCellCode(packBoxData.getCellCode());
            upperData.setBoxCode(boxCode);
            upperData.setWareId("285");
            upperAsn(upperData, currentUser);
        }

        //Step5.生成库存事务装箱
//        this.BatchInventoryTransact(pushAccept, currentUser);

    }

    /**
     * 批量上架
     *
     * @param transferBill
     */
    @Override
    public void batchBill(TransferBill transferBill) {

        List<Inventory> inventories = inventoryService.list(new QueryWrapper<Inventory>().in("box_code", transferBill.getToBoxCode()));
        for (Inventory inventory : inventories) {
            inventory.setCellCode(transferBill.getToCellCode());
            Integer integer = cellInfoService.findbyCellCode(transferBill.getToCellCode());
            inventory.setErpAreaId(integer);
        }

        inventoryService.updateBatchById(inventories);

    }

    @Override
    public void findCodes() {
        List<Inventory> inventory = baseMapper.findCellCode();
        inventory.forEach(item -> {
                    TransferBill transferBill = transferBillService.getOne(new QueryWrapper<TransferBill>().eq("to_box_code", item.getBoxCode()));
                    String toCellCode = transferBill.getToCellCode();
                    item.setCellCode(toCellCode);
                    item.setErpAreaId(cellInfoService.findbyCellCode(toCellCode));
                    item.getBoxCode();
                }
        );
        inventoryService.updateBatchById(inventory);
    }


    @Autowired
    private AreaInfoService areaInfoService;

    @Override
    public void saveBathInv() {
        List<Inventory> inventories = inventoryService.list(new QueryWrapper<Inventory>().isNull("cell_code"));
        for (Inventory inventory : inventories) {
            inventory.setCellCode(cellInfoService.findErpAreaId(inventory.getErpAreaId()));
        }
        inventoryService.updateBatchById(inventories);

        inventoryService.updateBatch();
        //        //处理批次
        this.batch();


        List<AreaInfo> areaInfos = areaInfoService.list();

//
        //过滤VMI物料
        List<Inventory> list = inventoryService.list(new QueryWrapper<Inventory>().ne("cell_code", 285000)
                .isNull("is_batch")
                .and(w -> w
                        //直发虚仓
                        .or().notIn("asn_stock_id", vmiId)
                        .or().isNull("asn_stock_id")
                )
        );
        Map<String, List<Inventory>> collect = list.stream().collect(Collectors.groupingBy(Inventory::getCellCodeAndItemCode));
        collect.forEach((key, val) -> {
            if (ObjectUtil.isEmpty(val)) {
                return;
            }
            Inventory inventory = val.stream().sorted(Comparator.comparing(Inventory::getBatchName, Comparator.nullsLast(String::compareTo))).findFirst().get();

            //降序
            double sum = val.stream().mapToDouble(Inventory::getQuantity).sum();
            Inventory inventory1 = new Inventory();
            BeanUtils.copyProperties(inventory, inventory1);
            inventory.setQuantity(sum);
            Set<Integer> ids = val.stream().map(Inventory::getInventoryId).collect(Collectors.toSet());
            inventory.setInventoryId(null);
            inventoryService.save(inventory);
            inventoryService.removeByIds(ids);
        });

        List<Inventory> saveBacth = new ArrayList<>();

        for (AreaInfo areaInfo : areaInfos) {
            Integer erpAreaId = areaInfo.getErpAreaId();
            if (ObjectUtil.isEmpty(erpAreaId)) {
                continue;
            }
            List<InventoryVo> inventory = pushErpService.inventory(new HashMap<>());
            for (InventoryVo inventoryVo : inventory) {
                if (ObjectUtil.isNotEmpty(inventoryVo.getBatchNo())) {
                    continue;
                }
                List<Inventory> inventoryList = inventoryService.list(new QueryWrapper<Inventory>().ne("cell_code", 285000)
                        .isNull("is_batch")
                        .and(w -> w
                                //直发虚仓
                                .or().notIn("asn_stock_id", vmiId)
                                .or().isNull("asn_stock_id")
                        )
                        .eq("item_code", inventoryVo.getItemNumber())
                        .eq("erp_area_id", erpAreaId)
                );

                if (ObjectUtil.isNotEmpty(inventoryList)) {
                    if (inventoryList.size() == 1) {
                        Inventory next = inventoryList.iterator().next();
                        next.setQuantity(inventoryVo.getQty());
                        next.setIsComp(1);
                        inventoryService.updateById(next);
                    } else {

                        List<Inventory> collect1 = inventoryList.stream().sorted(Comparator.comparing(Inventory::getBatchName, Comparator.nullsLast(String::compareTo)).reversed())
                                .collect(Collectors.toList());//降序
                        List<Inventory> insertInv = getInsertInv(inventoryVo.getQty(), collect1);
                        saveBacth.addAll(insertInv);
                    }

                } else {
                    Inventory newInv = new Inventory();
                    newInv.setWareId(285);
                    newInv.setWareName("如高高压");
                    newInv.setOrganizationId(-1);
                    newInv.setOrganizationName("自有");
                    newInv.setPackDetailId(33469);
                    newInv.setPackDescribe("件");
                    newInv.setErpAreaId(erpAreaId);
                    newInv.setIsComp(1);
                    newInv.setCellCode(cellInfoService.findErpAreaId(erpAreaId));
                    newInv.setItemCode(inventoryVo.getItemNumber());
                    ItemInfo itemInfo = itemInfoService.getOne(new QueryWrapper<ItemInfo>().eq("item_code", inventoryVo.getItemNumber()));
                    newInv.setItemName(Optional.ofNullable(itemInfo).map(item -> item.getItemName()).orElse(""));
                    newInv.setQuantity(inventoryVo.getQty());
                    newInv.setBoxCode(codeRuleService.generateCellCodeRedis());
                    inventoryService.save(newInv);
                }

            }


        }


        inventoryService.saveBatch(saveBacth);
        //库存取反，wms没有的库存
//        removeInv(areaInfos);

        //修改批次标记
        inventoryService.updateBatch();
    }


    public void removeInv(List<AreaInfo> areaInfos) {
        for (AreaInfo areaInfo : areaInfos) {
            Integer erpAreaId = areaInfo.getErpAreaId();
            if (ObjectUtil.isEmpty(erpAreaId)) {
                continue;
            }
            List<InventoryVo> inventory = pushErpService.inventory(new HashMap<>());
            List<String> collect = inventory.stream().map(InventoryVo::getItemNumberAndBatchNo).collect(Collectors.toList());
            List<String> itemNumbers = inventory.stream().map(InventoryVo::getItemNumber).collect(Collectors.toList());

            //过滤VMI物料
            List<Inventory> list = inventoryService.list(new QueryWrapper<Inventory>().ne("cell_code", 285000)
                    .eq("erp_area_id", erpAreaId)
                    .and(w -> w
                            //直发虚仓
                            .or().notIn("asn_stock_id", vmiId)
                            .or().isNull("asn_stock_id")));

            list.forEach(item -> {
                Integer isBatach = Optional.ofNullable(item.getIsBatch()).orElse(0);

                if (isBatach == 1) {
                    if (!collect.contains(item.getBatchNameAndItemCode())) {
                        inventoryService.removeById(item.getInventoryId());
                    }
                } else {
                    if (!itemNumbers.contains(item.getItemCode())) {
                        inventoryService.removeById(item.getInventoryId());
                    }
                }


            });

        }
    }


    public void batch() {

        List<AreaInfo> areaInfos = areaInfoService.list();
        for (AreaInfo areaInfo : areaInfos) {
            Integer erpAreaId = areaInfo.getErpAreaId();
            if (ObjectUtil.isEmpty(erpAreaId)) {
                continue;
            }
            List<InventoryVo> inventory = pushErpService.inventory(new HashMap<>());

            List<InventoryVo> inventoryVos = inventory.stream().filter(item -> ObjectUtil.isNotEmpty(item.getBatchNo())).collect(Collectors.toList());


            for (InventoryVo inventoryVo : inventoryVos) {

                if (inventoryVo.getItemNumber().equals("28.845.003.018") && inventoryVo.getBatchNo().equals("202231004")) {
                    System.out.println("111111");
                }
                List<Inventory> list = inventoryService.list(new QueryWrapper<Inventory>().eq("erp_area_id", erpAreaId)
                        .eq("batch_name", inventoryVo.getBatchNo())
                        .eq("item_code", inventoryVo.getItemNumber())
                );
                if (ObjectUtil.isNotEmpty(list)) {
                    List<Integer> collect = list.stream().map(item -> item.getInventoryId()).collect(Collectors.toList());
//                    if (collect.size() > 1) {
//                        collect.remove(1);
//                        inventoryService.removeByIds(collect);
//                    }
                    Inventory next = list.iterator().next();
                    next.setQuantity(inventoryVo.getQty());
                    next.setIsBatch(1);
                    next.setIsComp(1);
                    inventoryService.updateById(next);

                } else {
                    Inventory newInv = new Inventory();
                    newInv.setBatchName(inventoryVo.getBatchNo());
                    newInv.setWareId(285);
                    newInv.setWareName("如高高压");
                    newInv.setOrganizationId(-1);
                    newInv.setOrganizationName("自有");
                    newInv.setPackDetailId(33469);
                    newInv.setPackDescribe("件");
                    newInv.setIsComp(1);
                    newInv.setErpAreaId(erpAreaId);
                    newInv.setCellCode(cellInfoService.findErpAreaId(erpAreaId));
                    newInv.setItemCode(inventoryVo.getItemNumber());
                    ItemInfo itemInfo = itemInfoService.getOne(new QueryWrapper<ItemInfo>().eq("item_code", inventoryVo.getItemNumber()));
                    newInv.setItemName(Optional.ofNullable(itemInfo).map(item -> item.getItemName()).orElse(""));
                    newInv.setQuantity(inventoryVo.getQty());
                    newInv.setBoxCode(codeRuleService.generateCellCodeRedis());
                    newInv.setIsBatch(1);
                    inventoryService.save(newInv);
                }

            }
        }
    }


    public List<Inventory> getInsertInv(Double qty, List<Inventory> inventories) {
        double sum = inventories.stream().mapToDouble(Inventory::getQuantity).sum();
        if (sum < qty) {
            Inventory inventory = inventories.get(0);
            inventory.setQuantity(inventory.getQuantity() + (qty - sum));
        }
        ;


        List<Inventory> invList = new ArrayList<>();
        for (Inventory inv : inventories) {
            //待分配数量
            Inventory inventory = new Inventory();
            BeanUtils.copyProperties(inv, inventory);
            inventory.setIsComp(1);
            double soQty = inv.getQuantity();
            if (soQty == 0.00) {
                continue;
            }
            if (soQty >= qty) {
                inventory.setQuantity(qty);
                inventory.setInventoryId(null);
                invList.add(inventory);
                break;
            } else {
                inventory.setQuantity(soQty);
                inventory.setInventoryId(null);
                invList.add(inventory);
                qty -= soQty;
            }
        }
        Set<Integer> collect = inventories.stream().map(item -> item.getInventoryId()).collect(Collectors.toSet());
        inventoryService.removeByIds(collect);

        return invList;
    }

    @Autowired
    private AsnDetailService asnDetailService;


    @Autowired
    private SuppInfoMapper suppInfoMapper;

    @Autowired

    private DeptService deptService;

    @Override
    public void upperAsn(UpperData upperData, CurrentUser currentUser) {
        if (ObjectUtil.isEmpty(upperData.getCellCode())) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "请扫描目标库位！");
        }
        Dept dept = new Dept();
        Integer supperId;
        //供应商名称
        if (ObjectUtil.isNotEmpty(upperData.getSupplierId()) && upperData.getSupplierId() != 0) {
            SupplierInfo supplierInfo = suppInfoMapper.selectById(upperData.getSupplierId());
            if (ObjectUtil.isNotEmpty(supplierInfo)) {
                upperData.setSupplierName(supplierInfo.getSupName());
            }
        }
        Integer erpAreaId = cellInfoService.findbyCellCode(upperData.getCellCode());
        //验证库区
        List<TransferBill> transferBills = new ArrayList<>();
        String boxCode = upperData.getBoxCode();
        List<Inventory> inventories = inventoryService.list(new QueryWrapper<Inventory>().eq("box_code", boxCode)
                .notIn("cell_code", 285000, 285333)
        );
        if (ObjectUtil.isNotEmpty(inventories)) {
            Set<Integer> oldErpAreaId = inventories.stream().map(Inventory::getErpAreaId).collect(Collectors.toSet());
            Set<String> cellSet = inventories.stream().map(Inventory::getCellCode).collect(Collectors.toSet());

            if (!oldErpAreaId.contains(erpAreaId)) {
                throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "不可跨库区存放");
            }
            if (!cellSet.contains(upperData.getCellCode())) {
                throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "该容器已在" + cellSet.iterator().next() + "货位存在");
            }

        }
        inventoryService.updateBatchById(inventories);

        //部门名称
        if (ObjectUtil.isNotEmpty(upperData.getDeptId())) {
            dept = deptService.getById(upperData.getDeptId());
            upperData.setDeptName(dept.getDeptName());
        }
        List<AsnDetail> asnDetails = new ArrayList<>();
        if (ObjectUtil.isEmpty(erpAreaId)) {
            throw new ServiceException(CommonCode.FREEZE_ERROR, "目标库位不存在");
        }
        for (Inventory inventory : upperData.getInventories()) {
            TransferBill newTransferBill = new TransferBill();
            TransferBill transferBill = transferBillService.getOne(
                    new QueryWrapper<TransferBill>().eq("inventory_id", inventory.getInventoryId())
                            .eq("state", 0)
            );
            BeanUtils.copyProperties(transferBill, newTransferBill);
            transferBill.setState(2);
            transferBill.setToBoxCode(null);
            transferBillService.removeById(transferBill);
            newTransferBill.setToCellCode(upperData.getCellCode());
            newTransferBill.setId(null);
            newTransferBill.setBillType(2);
            transferBills.add(newTransferBill);
            AsnDetail asnDetail = asnDetailService.getOne(new QueryWrapper<AsnDetail>().eq("detail_no", inventory.getAsnDetailNo()));
            asnDetail.setBatchName(newTransferBill.getBatchName());
            asnDetail.setMtoNo(inventory.getMtoNo());
            asnDetail.setStockId(erpAreaId);
            //数量
            asnDetail.setQty(inventory.getQuantity());
            asnDetail.setErpStockId(inventory.getAsnStockId());
            asnDetails.add(asnDetail);
        }
        //生成库存事务
        transferBillService.confirmTransferBill(transferBills);
        AsnMaster asnMaster = asnMasterMapper.selectOne(new QueryWrapper<AsnMaster>().eq("bill_no", asnDetails.get(0).getBillNo()));
        BaseAssist enterAssist = new BaseAssist();
        enterAssist.setDeptId(dept.getDeptId());
        enterAssist.setCellCode(upperData.getCellCode());
        enterAssist.setSupplierId(asnMaster.getSupplierId());
        strategyEnterService.resolveAsn(asnMaster, asnDetails, enterAssist);
    }

    /**
     * 生产退料
     *
     * @param soDetails
     * @param billNo
     * @param currentUser
     */
    @Override
    public void PDreturn(List<SoDetail> soDetails, String billNo, CurrentUser currentUser) {


        SoMaster soMaster = soMasterService.getOne(new QueryWrapper<SoMaster>().eq("bill_no", billNo));
        AsnMaster asnMaster = new AsnMaster();
        String soTableName = "asn_master";
        Integer soNextId = validatorService.getNextId(soTableName);
        String asnBillNo = soMaster.getBillNo() + "-" + soNextId;
        asnMaster.setCreateUserId(currentUser.getUserId());
        asnMaster.setCreateUserName(currentUser.getUserName());
        asnMaster.setCreateTime(LocalDateTime.now());
        asnMaster.setOrderBillNo(soMaster.getOrderBillNo());
        asnMaster.setBillNo(asnBillNo);
        asnMaster.setBillType(soMaster.getBillType());
        asnMaster.setWareId(285);
        asnMaster.setWareCode("rggy");
        asnMaster.setWareName("如皋高压");
        asnMaster.setMemo(soDetails.iterator().next().getRemake());
        asnMaster.setOrganizationId(-1);
        asnMaster.setOrganizationName("自有");
        asnMaster.setOrganizationCode("SYS_MINE");

        asnMaster.setBillSource(0);
        asnMaster.setBeforeNum(soMaster.getBeforeNum());
        asnMaster.setUda1(soMaster.getSoTypeName());
        asnMaster.setAsnState(0);
        asnMaster.setSupplierId(soMaster.getSupplierId());
        asnMaster.setSupplierName(soMaster.getSupplierName());
        asnMaster.setDeptId(soMaster.getDeptId());
        asnMaster.setUda3(soMaster.getDeptName());
        asnMaster.setAsnType(soMaster.getSoType());

        List<AsnDetail> asnDetails = new ArrayList<>();
        for (SoDetail soDetail : soDetails) {
            if (soDetail.getDeliveryQuantity() - soDetail.getReturnQty() <= 0) {
                continue;
            }
            //修改分配数量
            soDetail.setReturnQty(soDetail.getReturnQty() + soDetail.getNewReturnQty());
            AsnDetail asnDetail = new AsnDetail();
            asnDetail.setBillNo(asnMaster.getBillNo());//ASN单号
            asnDetail.setPackDetailId(33469);//基本单位ID
            asnDetail.setItemCode(soDetail.getItemCode());//物料编码
            asnDetail.setItemName(soDetail.getItemName());//物料名称
            asnDetail.setSourceId(soMaster.getBeforeNum());
            asnDetail.setUda1(soDetail.getModel());//规格型号
            asnDetail.setDetailNo(asnMaster.getBillNo() + "-" + soDetail.getBomSplit());
//                                    asnDetail.setTransRatio(purchaseOrderDetailBO.getAuxQty());//数量

            asnDetail.setExpectQuantity(soDetail.getNewReturnQty());//基本单位数量

            asnDetail.setRowIndex(soDetail.getBomSplit());//行号
            //目标单据红蓝字
            asnDetail.setRob(false);
            asnDetails.add(asnDetail);
        }
        soDetailService.updateBatchById(soDetails);
        //入库任务
        asnMasterService.save(asnMaster);
        //入库任务明细
        asnDetailService.saveBatch(asnDetails);
        acceptRecordService.pdaBatchAccept(asnMaster, currentUser);

    }

    /**
     * PC一键上架
     *
     * @param packBoxData
     * @param currentUser
     */
    @Override
    public void createboxWeb(PackBox packBoxData, CurrentUser currentUser) {
        AsnMaster asnMaster = asnMasterService.getOne(new QueryWrapper<AsnMaster>().eq("bill_no", packBoxData.getAcceptList().iterator().next().getAsnBillNo()).last("limit 1"));

        //Step0. 准备数据
        List<TransferBill> transferBills = new ArrayList<>();
        List<AsnCodeDetail> asnCodeDetails = new ArrayList<>();
        List<AcceptRecord> list = new ArrayList<>();


        //Step2.合并详情集合，并累加数量
        //    Step2.1 合并集合详情并Set容器码
        //    Step2.1 合并集合详情并Set容器码
        List<AcceptRecord> pushAccept = packBoxData.getAcceptList().stream().map(item -> {
            item.setBoxCode(packBoxData.getBoxCode());

            return item;
        }).collect(Collectors.toList());

        Map<Integer, List<AcceptRecord>> acceptMap = pushAccept.stream().collect(Collectors.groupingBy(item -> item.getId()));
        //    Step2.2修改装箱数量
        acceptMap.forEach((id, val) -> {
            AcceptRecord record = acceptMap.get(id).iterator().next();
            double sum = val.stream().mapToDouble(AcceptRecord::getPcs).sum();
            record.setPackedQuantity(record.getPackedQuantity() + sum);
            record.setUpUserId(currentUser.getUserId());
            record.setPcs(record.getQualifiedQuantity());
            record.setUpUserName(currentUser.getUserName());
            list.add(record);
        });

        String boxCode = "";
        //Step3. 获取装箱单明细并赋值
        //Step3.1遍历装箱列表
//        for (PackBox packBox : packBoxData.getAcceptList()) {
        boxCode = packBoxData.getBoxCode();
        for (AcceptRecord acceptRecord : packBoxData.getAcceptList()) {
            TransferBill transferBill = new TransferBill();
            transferBill.setItemName(acceptRecord.getItemName());
            //仓库
            transferBill.setWareId(acceptRecord.getWareId());
            //转移单类型
            transferBill.setBillType(InStockConstant.TRANS_TYPE_PACK_BOX);
            //来源库位 收货区库位   无目标库位
            transferBill.setFromCellCode(acceptRecord.getCellCode());
            transferBill.setToCellCode(acceptRecord.getCellCode());
            //asn单号
            transferBill.setUda1(acceptRecord.getAsnBillNo().trim());
            transferBill.setAsnStockId(acceptRecord.getAsnStockId());
            transferBill.setAsnStockName(acceptRecord.getAsnStockName());
            //无来源容器  目标容器
            transferBill.setToBoxCode(acceptRecord.getBoxCode());
            transferBill.setItemCode(acceptRecord.getItemCode());
            transferBill.setBatchName(acceptRecord.getBatchName());
            transferBill.setPackDetailId(acceptRecord.getPackDetailId());
            transferBill.setQty(new BigDecimal(acceptRecord.getQualifiedQuantity()));
            //单号
            transferBill.setTransferBillCode(codeRuleService.generateCodeByRedis(SystemManageConstant.CODE_RULE_TRANS));
            //状态
            transferBill.setState(InStockConstant.TRANS_STATE_INIT);
            //标记冻结解冻标识
            if (AsnManageConstant.ACCEPT_QC_STATE_TODO.equals(acceptRecord.getQcState())) {
                //说明是待检的物料
                transferBill.setFreezeFlag(AsnManageConstant.ACCEPT_QC_STATE_TODO);
            }
            //确认人
            transferBill.setConfirmUserId(currentUser.getUserId());
            transferBill.setConfirmUserName(currentUser.getUserName());
            //收货单编码
            transferBill.setUda2(acceptRecord.getAsnDetailNo());

            acceptRecord.setCategoryId(asnMaster.getCategoryId());

            InventoryTransact inventoryTransact = this.toRequestAccept(acceptRecord, currentUser);
            int inventoryId = inventoryTransactService.run(inventoryTransact);
            transferBill.setInventoryId(inventoryId);
            transferBills.add(transferBill);
//            }


        }
        //Step4.新增或修改 装箱单，收货单，详情列表
        transferBillService.saveBatch(transferBills);
        //收货单
        acceptRecordService.updateBatchById(list);
        //详情设计到出库回传
        asnCodeDetailService.saveBatch(asnCodeDetails);
        //如果有库位，则直接上架
        if (ObjectUtil.isNotEmpty(packBoxData.getCellCode())) {
            UpperData upperData = new UpperData();
            QueryWrapper<Inventory> queryWrapper = new QueryWrapper();
            queryWrapper.eq("asn_bill_no", packBoxData.getAcceptList().iterator().next().getAsnBillNo().trim());
            queryWrapper.eq("box_code", boxCode);
            queryWrapper.eq("cell_code", 285000);
            upperData.setInventories(inventoryService.list(queryWrapper));
            upperData.setCellCode(packBoxData.getCellCode());
            upperData.setBoxCode(boxCode);
            upperData.setWareId("285");
            upperAsn(upperData, currentUser);
        }
    }

    @Override
    public List<InventoryExcel> dowLoadList(InventoryCriteria criteria) {
        log.info(criteria.getPageNum() + criteria.getPageSize() + "");
        List<InventoryExcel> inventoryExcels = inventoryService.dowLoadList(criteria);
        if (ObjectUtil.isEmpty(inventoryExcels)) {
            return new ArrayList<InventoryExcel>();
        }
        List<Integer> invIds = inventoryExcels.stream().map(item -> item.getInventoryId()).collect(Collectors.toList());
        List<TransferBill> transferBillList = transferBillService.list(new QueryWrapper<TransferBill>().in("inventory_id", invIds));
        Map<Integer, TransferBill> tranMap = convertMap(transferBillList, TransferBill::getInventoryId);
        inventoryExcels.parallelStream().map(item -> {
                    item.setConfirmUserName(
                            Optional.ofNullable(tranMap.get(item.getInventoryId())).map(menu -> menu.getConfirmUserName()).orElse(""));
                    return item;
                }
        ).collect(Collectors.toList());
        return inventoryExcels;
    }


    //生成装箱单
    public InventoryTransact toRequestAccept(AcceptRecord acceptRecord, CurrentUser currentUser) {

        AsnMaster asnMaster = asnMasterService.getOne(new QueryWrapper<AsnMaster>()
                .eq("bill_no", acceptRecord.getAsnBillNo())
        );

        InventoryTransact inventoryTransact = new InventoryTransact();
        inventoryTransact.setAsnType(asnMaster.getAsnType());
        //Step1.准备数据
        //仓库
        inventoryTransact.setWareId(acceptRecord.getWareId());
        inventoryTransact.setWareName(acceptRecord.getWareName());
        //库位
        inventoryTransact.setFromCellCode(acceptRecord.getCellCode());
//        inventoryTransact.setToCellCode(acceptRecord.getToCellCode());
        //容器
        inventoryTransact.setFromBoxCode(acceptRecord.getBoxCode());
        inventoryTransact.setToBoxCode(acceptRecord.getBoxCode());
        //物料
        inventoryTransact.setItemCode(acceptRecord.getItemCode());
        inventoryTransact.setItemName(acceptRecord.getItemName());
        //批次
        inventoryTransact.setFromBatchId(acceptRecord.getBatchId());
        inventoryTransact.setFromBatchName(acceptRecord.getBatchName());
        inventoryTransact.setToBatchId(acceptRecord.getBatchId());
        inventoryTransact.setToBatchName(acceptRecord.getBatchName());
        //数量
        inventoryTransact.setToQuantity(acceptRecord.getPcs().doubleValue());
        //包装 转换率
        inventoryTransact.setFromPackDetailId(acceptRecord.getPackDetailId());
        inventoryTransact.setToPackDetailId(acceptRecord.getPackDetailId());
        inventoryTransact.setToTransRatio(new Double(1));
        inventoryTransact.setFromTransRatio(new Double(1));
        //创建人 时间
        inventoryTransact.setCreateUserId(currentUser.getUserId());
        inventoryTransact.setCreateUserName(currentUser.getUserName());
        inventoryTransact.setCreateTime(DateUtil.now());
        //事务类型 4装箱单
        inventoryTransact.setTransactType(4);
        //来源单据号
//        inventoryTransact.setBillNo(transferBill.getTransferBillCode());
        //冻结标识
//        inventoryTransact.setState(transferBill.getFreezeFlag());
        inventoryTransact.setAsnStockId(acceptRecord.getAsnStockId());
        inventoryTransact.setAsnStockName(acceptRecord.getAsnStockName());
        inventoryTransact.setAgreementNo(acceptRecord.getAgreementNo());
        inventoryTransact.setCategoryId(inventoryTransact.getCategoryId());


        //单号
        inventoryTransact.setBillNo(acceptRecord.getAsnBillNo());
        //详情
        inventoryTransact.setDetailNo(acceptRecord.getAsnDetailNo());
        inventoryTransact.setToInventoryId(acceptRecord.getInventoryId());

        //Step2.保存，返回
        inventoryTransactService.save(inventoryTransact);
        return inventoryTransact;
    }


    public OrderToErpBO getBean(ErpPushLog erpPushLog, List<ErpPushLogInfo> detail) {
        OrderToErpBO orderToErpBO = new OrderToErpBO();
        BeanUtils.copyProperties(erpPushLog, orderToErpBO);
        orderToErpBO.setBillDate(DateUtils.getNowDateString());
        List<OrderDetailBO> orderDetailBOList = new ArrayList<>();
        detail.forEach(item -> {
            OrderDetailBO orderDetailBO = new OrderDetailBO();
            BeanUtils.copyProperties(item, orderDetailBO);
            orderDetailBOList.add(orderDetailBO);
        });
        orderToErpBO.setDetails(orderDetailBOList);
        return orderToErpBO;

    }

    public void merge(List<ErpPushLogInfo> list, Map<String, List<Inventory>> inventoryMap, List<Inventory> inventoryList, List<TransferBill> transferBills, Boolean flg) {
        for (ErpPushLogInfo erpPushLogInfo : list) {
            TransferBill transferBill = new TransferBill();
            //查找库存
            Inventory inventory = inventoryMap.get(erpPushLogInfo.getBoxCode()).iterator().next();
            //修改库存
            if (flg) {
                inventory.setQuantity(inventory.getQuantity() - erpPushLogInfo.getQty());
            }
            //生成转移任务
            BeanUtils.copyProperties(inventory, transferBill);
            String code = codeRuleService.generateCode(SystemManageConstant.CODE_RULE_TRANS);
            transferBill.setTransferBillCode(code);
            transferBill.setBillType(4);
            transferBill.setState(0);
            transferBill.setFromCellCode(inventory.getCellCode());
            transferBill.setFromBoxCode(inventory.getBoxCode());
            transferBill.setQty(BigDecimal.valueOf(inventory.getQuantity()));
            transferBills.add(transferBill);
            inventoryList.add(inventory);
        }
    }
}